<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebsocketClient</title>
</head>
<body>
    <select onchange="this.options[this.options.selectedIndex].onclick()">
        <option onclick="switchProtocol('websocket', 8500)">websocket</option>
        <option onclick="switchProtocol('tcp', 13329)">tcp</option>
    </select>
    <form onsubmit="return false">
        <label>module:</label>
        <input name="module" id="module" type="number" value="3"/><br>
        <label>cmd:</label>
        <input name="cmd" id="cmd" type="number" value="0"/><br>
        <textarea id="message" name="message" style="height: 300px; width: 300px"></textarea>
        <input type="button" value="发送消息" onclick="doSend()">
        <textarea id="responseText" style="height: 300px; width: 300px"></textarea>
        <input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''">
    </form>
</body>

<script src="lib/protobuf.min.js"></script>
<script src="script/config.js"></script>
<script src="script/protocol.js"></script>
<script>
    var socket;
    var byteBuf = [];
    var totalLen = 0;

    // document.getElementById("message").value = "{\"id\": 2}";
    // document.getElementById("message").value = "{\"account\": \"cwjokaka\", \"password\": \"33207a\"}";
    document.getElementById("message").value = "{\"text\": \"haha\"}";

    // 判断当前浏览器是否支持websocket
    if(window.WebSocket) {
        initWebsocket(8500);
    } else {
        alert("当前浏览器不支持websocket")
    }

    function initWebsocket(port) {
        // 如果之前有连接，则先关闭
        if (socket && socket.readyState === WebSocket.OPEN) {
            appendText("关闭旧连接...");
            socket.close();
        }
        byteBuf = [];
        totalLen = 0;
        socket = new WebSocket(`ws://localhost:${port}/ws`);
        // websocket默认是字符串传输，这里改为字节流
        socket.binaryType = "arraybuffer";
        //相当于channelRead, ev 收到服务器端回送的消息
        socket.onmessage = function (ev) {
            console.log('收到服务端消息:');
            doReceive(ev.data);
        };

        // 相当于连接开启(感知到连接开启)
        socket.onopen = function (ev) {
            appendText("新连接开启了..");
        };

        // 相当于连接关闭(感知到连接关闭)
        socket.onclose = function (ev) {
            appendText("连接关闭了..");
        }
    }

    function switchProtocol(type, port) {
        newText(`切换${type}连接...`);
        initWebsocket(port);
    }

    /**
     * 接收指令
     */
    function doReceive(buffer) {
        // 读取一字节到缓冲区中
        byteBuf = byteBuf.concat(Array.from(new Uint8Array(buffer)));
        // 前两个字节是协议总长度
        if (byteBuf.length < 2) {
            console.log("协议不足2字节");
            return;
        }
        // 获取协议总长度(2byte)
        let dataview = new DataView(new Uint8Array(byteBuf).buffer);
        totalLen = dataview.getUint16(0);
        console.log("获取数据包总长度:" + (totalLen + 2));
        if (byteBuf.length < totalLen + 2) {
            return;
        }
        let module = dataview.getUint16(2);
        let cmd = dataview.getUint8(4);
        console.log("module:" + module + ", cmd:" + cmd);
        let param_body = dataview.buffer.slice(5, totalLen + 2);
        let bytes = new Uint8Array(param_body);
        let rt = document.getElementById("responseText");
        try {
            // debugger
            let data = decode(module, cmd, bytes);
            rt.value = rt.value + "\n" + "服务端返回module:" + module +
                ", cmd:" + cmd +
                ", data:" + JSON.stringify(data);
        } catch (e) {
            rt.value = rt.value + "\n" + "服务端module:" + module +
                ", cmd:" + cmd +
                ", protobuf解析出错:" + e;
        } finally {
            byteBuf = [];
        }
    }

    /**
     * 发送指令
     */
    function doSend() {
        if(!window.socket) { //先判断socket是否创建好
            return;
        }
        if(socket.readyState !== WebSocket.OPEN) {
            alert("连接没有开启");
            return;
        }
        // short
        let module = parseInt(document.getElementById("module").value);
        // byte
        let cmd =  parseInt(document.getElementById("cmd").value);
        // byte[]
        let message = document.getElementById("message").value;
        // console.log(module, cmd, message);
        let payload = JSON.parse(message);

        let msgBuffer = encode(module, cmd, payload);
        // 字节数组
        let buffer = new ArrayBuffer(msgBuffer.byteLength + 5);
        // 视图对象用于操作ArrayBuffer
        let view = new DataView(buffer);
        // 加入total_len(short)
        view.setUint16(0, 3 + msgBuffer.byteLength);
        // 加入module(short)
        view.setUint16(2, module);
        // 加入cmd(byte)
        view.setUint8(4, cmd);
        for (let i = 0; i < msgBuffer.byteLength; i++) {
            view.setUint8(i + 5, msgBuffer[i]);
        }
        // send的是ArrayBuffer | DataView
        socket.send(view);

    }

    function appendText(text) {
        let rt = document.getElementById("responseText");
        rt.value = rt.value + "\n" + text;
    }

    function newText(text) {
        let rt = document.getElementById("responseText");
        rt.value = text;
    }

</script>

</html>